package implementations.dm_kernel.host;

import implementations.dm_kernel.MessageControlImpl;
import implementations.dm_kernel.MessageResultImpl;
import implementations.sm_kernel.JCL_FacadeImpl;
import interfaces.kernel.JCL_facade;
import interfaces.kernel.JCL_message;
import interfaces.kernel.JCL_message_commons;
import interfaces.kernel.JCL_message_control;
import interfaces.kernel.JCL_message_global_var;
import interfaces.kernel.JCL_message_register;
import interfaces.kernel.JCL_message_result;
import interfaces.kernel.JCL_message_task;
import interfaces.kernel.JCL_result;

import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import commom.GenericConsumer;
import commom.GenericResource;
import commom.JCL_resultImpl;

// exemplo de um consumidor !!!

/*
 * MESSAGES
 * 
 *  1 public boolean register(File[] f, String classToBeExecuted) {
    2 public boolean unRegister(String nickName) {
    4 public String execute(String objectNickname, Object... args) {
	5 public String execute(String className, String methodName, Object... args) {
	6 public JCL_result getResultBlocking(String ID) {
	7 public JCL_result getResultUnblocking(String ID) {
	8 public JCL_result removeResult(String ID) {
	9 public Object instantiateGlobalVar(String varName, Class<?> varType,
	10 public boolean instantiateGlobalVar(String varName, Object instance) {
	11 public boolean destroyGlobalVar(String varName) {
	12 public boolean setValue(String varName, Object value) {
	13 public boolean setValueUnlocking(String varName, Object value) {
	14 public JCL_result getValue(String varName) {
	15 public JCL_result getValueLocking(String varName) {
	16 public void destroy() {
	18 public boolean containsTask(String nickName){
	
	type 17 is containsGlobalVar. It is used only by JCL server
	
	METHOD DEPRECATED in JCL distributed version: public boolean register(Class<?> object, String nickName) {
	
	-1 slave register

 */

public class SocketConsumer<S extends Socket> extends GenericConsumer<S>{
	
	private JCL_facade jcl;
	
	public SocketConsumer(GenericResource<S> re) {
		
		super(re);	
		
		jcl = JCL_FacadeImpl.getInstance();
	}

	@Override
	protected void doSomething(S str) {
		try{
			// TODO Auto-generated method stub
			ObjectInputStream in = new ObjectInputStream(str.getInputStream());
			JCL_message msg = (JCL_message) in.readObject();
			switch (msg.getType()){
			case 1:{	
				
				JCL_message_register msgR = (JCL_message_register) msg;
				File [] fS = new File[msgR.getJars().length];
				for(int i=0; i< fS.length; i++){
					FileOutputStream fout = new FileOutputStream("../jcl_temp/"+msgR.getJarsNames()[i]);
					fout.write(msgR.getJars()[i]);
					fout.flush();
					fout.close();
					fS[i] = new File("../jcl_temp/" + msgR.getJarsNames()[i]);
				}				
				
				System.err.println("Registering Class Name: " + msgR.getClassName());
				Boolean b = new Boolean(jcl.register(fS, msgR.getClassName()));
				JCL_result r = new JCL_resultImpl();
				r.setCorrectResult(b);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(1);
				RESULT.setResult(r);
				
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				in.close();
						
				break;
			}
			case 2:{	
				
				JCL_message_commons jclC = (JCL_message_commons)msg;
				boolean b = jcl.unRegister(jclC.getRegisterData()[0]);
				
				JCL_result r = new JCL_resultImpl();
				r.setCorrectResult(b);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(2);
				RESULT.setResult(r);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			
			case 4:{				
				JCL_message_task jclT = (JCL_message_task) msg;
				
				String ticket = jcl.execute(jclT.getTask().getObjectName(), jclT.getTask().getMethodParameters());
				
				JCL_result r = new JCL_resultImpl();
				r.setCorrectResult(ticket);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(4);
				RESULT.setResult(r);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 5:{		
				
				JCL_message_task jclT = (JCL_message_task) msg;
				
				String ticket = jcl.execute(jclT.getTask().getObjectName(), jclT.getTask().getObjectMethod(), jclT.getTask().getMethodParameters());
				
				JCL_result r = new JCL_resultImpl();
				r.setCorrectResult(ticket);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(5);
				RESULT.setResult(r);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 6:{	
				
				JCL_message_commons jclC = (JCL_message_commons)msg;
				JCL_result jclR = jcl.getResultBlocking(jclC.getRegisterData()[0]);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(6);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 7:{				
				
				JCL_message_commons jclC = (JCL_message_commons)msg;
				JCL_result jclR = jcl.getResultUnblocking(jclC.getRegisterData()[0]);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(7);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 8:{				
				
				JCL_message_commons jclC = (JCL_message_commons)msg;
				JCL_result jclR = jcl.removeResult(jclC.getRegisterData()[0]);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(8);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 9:{				
				
				JCL_message_global_var jclGV = (JCL_message_global_var)msg;
				JCL_result jclR = new JCL_resultImpl();
				
				File [] fS = new File[jclGV.getJars().length];
				for(int i=0; i< fS.length; i++){
					FileOutputStream fout = new FileOutputStream("../jcl_temp/"+jclGV.getJarsNames()[i]);
					fout.write(jclGV.getJars()[i]);
					fout.flush();
					fout.close();
					fS[i] = new File("../jcl_temp/" + jclGV.getJarsNames()[i]);
				}	
						
				jclR.setCorrectResult(jcl.instantiateGlobalVar(jclGV.getNickName(), jclGV.getVarName(), fS, jclGV.getDefaultValues()));
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(9);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 10:{				
				JCL_message_global_var jclGV = (JCL_message_global_var)msg;
				JCL_result jclR = new JCL_resultImpl();
						
				jclR.setCorrectResult(jcl.instantiateGlobalVar(jclGV.getVarName(), jclGV.getVarInstance()));
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(10);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 11:{				
				
				JCL_message_commons jclC = (JCL_message_commons)msg;
				JCL_result jclR = new JCL_resultImpl();
						
				jclR.setCorrectResult(jcl.destroyGlobalVar(jclC.getRegisterData()[0]));
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(11);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 12:{
				JCL_message_global_var jclGV = (JCL_message_global_var)msg;
				JCL_result jclR = new JCL_resultImpl();
						
				jclR.setCorrectResult(new Boolean(jcl.setValue(jclGV.getVarName(), jclGV.getVarInstance())));
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(12);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 13:{				
				JCL_message_global_var jclGV = (JCL_message_global_var)msg;
				JCL_result jclR = new JCL_resultImpl();
						
				jclR.setCorrectResult(new Boolean(jcl.setValueUnlocking(jclGV.getVarName(), jclGV.getVarInstance())));
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(13);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 14:{				
				JCL_message_commons jclC = (JCL_message_commons)msg;
				JCL_result jclR = jcl.getValue(jclC.getRegisterData()[0]);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(14);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 15:{				
				JCL_message_commons jclC = (JCL_message_commons)msg;
				JCL_result jclR = jcl.getValueLocking(jclC.getRegisterData()[0]);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(15);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
				
				break;
			}
			case 16:{	
				//devemos parar todos os slaves antes...
				JCL_result jclR = new JCL_resultImpl();
				jcl.destroy();	
				jclR.setCorrectResult(true);
				
				JCL_message_result RESULT = new MessageResultImpl();
				RESULT.setType(16);
				RESULT.setResult(jclR);
				
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(RESULT);
				out.flush();
				out.close();
				
				in.close();
												
				re.stopServer();
				re.setFinished();
				break;
			}	
			
			case 18:{				
				JCL_message_control aux = (JCL_message_control) msg;
				boolean b = this.jcl.containsTask(aux.getRegisterData()[0]);
				JCL_message_control resp = new MessageControlImpl();
				resp.setRegisterData(String.valueOf(b));
				ObjectOutputStream out = new ObjectOutputStream(str.getOutputStream());
				out.writeObject(resp);
				out.flush();
				out.close();
				in.close();
				break;
			}
			
			}
			
			
			str.close();
				
		}catch (Exception e){
			e.printStackTrace();
			
		}
				
	}	

}
